/*
 *
 *
 */

#include "gkt_gpio.h"
#include "gkt_window.h"
#include "key_common.h"
#include "gkt_led.h"

#ifdef GKT_CONFIG_KEY_LED_MAP_TABLE

#define GKT_KEY_LED_MAP(_name)	GKT_LED_ID(_name)
static const uint32_t sc_key_led_map_table[] = {
	GKT_CONFIG_KEY_LED_MAP_TABLE
};
#define KEY_LED_MAP_TABLE_SIZE	\
	(sizeof(sc_key_led_map_table) / sizeof(uint32_t))

static void key_led_bright(uint32_t key_bits)
{
	uint32_t i, on_led_bits, off_led_bits;

	gkt_trace("key_led_bright: key_bits(0x%x)\n", key_bits);

	on_led_bits = 0;
	for (i = 0; i < KEY_LED_MAP_TABLE_SIZE; i++) {
		if (key_bits & (1U << (i & 0x1f)))
			on_led_bits |= 1U << sc_key_led_map_table[i];
	}
	off_led_bits = g_key_manage.all_led_bits & (~on_led_bits);

	gkt_led_lighten(off_led_bits, on_led_bits);
	
	if (g_key_manage.on_led_bits != on_led_bits) {
		g_key_manage.on_led_bits = on_led_bits;
		// TODO: set keypad flag
		gkt_keypad_update_base_freqs();
	}
}

void gkt_key_led_control(uint32_t ctrl, uint32_t data)
{
	uint32_t key_bits;

	gkt_trace("key_led: ctrl(%u), data(0x%x)\n", ctrl, data);

	if (GKT_KEY_LED_CTRL_ENABLE == ctrl) {
		if (data)
			g_key_manage.flags |= KEY_F_LED_ENABLE;
		else
			g_key_manage.flags &= ~KEY_F_LED_ENABLE;
	}
	else if (GKT_KEY_LED_CTRL_BRIGHT == ctrl)
		g_key_manage.on_key_bits = data;
	else if (GKT_KEY_LED_CTRL_ALL_ON == ctrl) {
		if (data)
			g_key_manage.all_on_counter++;
		else if (g_key_manage.all_on_counter > 0)
			g_key_manage.all_on_counter--;
	}
	else
		return;

	if (g_key_manage.flags & KEY_F_LED_ENABLE) {
		key_bits = (g_key_manage.all_on_counter > 0) ? 
						(~0) : g_key_manage.on_key_bits;
	}
	else
		key_bits = 0;
	gkt_trace("key_led: (0x%x) (0x%x - 0x%x - 0x%x)\n",
			g_key_manage.flags, key_bits, 
			g_key_manage.on_key_bits, g_key_manage.unmask_bits);
	
	key_led_bright(key_bits);
}

#if GKT_KEY_LED_FLICKER_ENABLE

#define KEY_LED_FLICKER_F_FIELD(flags, field_name)	\
	((flags & GKT_KEY_LED_FLICKER_F_##field_name##_MASK) >> GKT_KEY_LED_FLICKER_F_##field_name##_SHIFT)
static void key_led_flicker_notify(gkt_led_flicker_state_e state, 
				uint32_t private_data)
{
	gkt_event_s event;

	if ((g_key_manage.flags & KEY_F_LED_FLICKING) 
		&& (private_data == g_key_manage.seq))
	{
		g_key_manage.flags &= ~KEY_F_LED_FLICKING;
	
		event.window_id = GKT_WINDOW_ID_ACTIVE;
		event.flags = GKT_EVENT_F_BYPASS;
		event.major_type = GKT_EVENT_KEY;
		event.minor_type = GKT_KEY_MINOR_LED_FLICKER_END;
		gkt_event_put(&event, GKT_IMMEDIATELY);
	}
}

static int key_led_flicker_init(const uint32_t *frames_key_bits, 
			uint32_t frame_nums, uint32_t flags, 
			gkt_led_flicker_params_s *led_flicker_params)
{
	uint32_t i, mask;
	uint32_t frame_key_bits, frame_index;

	led_flicker_params->flags = 0;

	frame_index = 0;
	while (frame_index < frame_nums) {
		frame_key_bits = frames_key_bits[frame_index];
		g_key_manage.frames_led_bits[frame_index] = 0;
		for (i = 0; i < GKT_KEY_MAX; i++) {
			mask = 1U << i;
			if (frame_key_bits & mask)
				g_key_manage.frames_led_bits[frame_index] |= 1U << sc_key_led_map_table[i];
		}
		if (!g_key_manage.frames_led_bits[frame_index]) {
			gkt_error("key_led_flicker: frame(%u) no key led will be shined!\n", frame_index);
			return GKT_EPARAM;
		}

		frame_index++;
	}
	led_flicker_params->frame_nums = frame_nums;
	led_flicker_params->frame_led_bits = &g_key_manage.frames_led_bits[0];
	led_flicker_params->all_led_bits = g_key_manage.all_led_bits;

	/* cycles */
	if (flags & GKT_KEY_LED_FLICKER_F_CYCLES_INFINITE)
		led_flicker_params->cycles = ~0;
	else
		led_flicker_params->cycles = KEY_LED_FLICKER_F_FIELD(flags, CYCLES);

	/* frame time */
	led_flicker_params->frame_time = KEY_LED_FLICKER_F_FIELD(flags, FRAME_TIME);
	if (led_flicker_params->frame_time > 0)
		led_flicker_params->frame_time = ((led_flicker_params->frame_time + 9) / 10) * 10;

	led_flicker_params->private_data = ++g_key_manage.seq;
	led_flicker_params->notify_fn = key_led_flicker_notify;
	
	return GKT_SUCCESS;
}

#ifdef GKT_CONFIG_KEY_LED_MARQUEE_CYCLES_DEFAULT
#define KEY_LED_MARQUEE_CYCLES_DEFAULT	\
	GKT_CONFIG_KEY_LED_MARQUEE_CYCLES_DEFAULT
#else
#define KEY_LED_MARQUEE_CYCLES_DEFAULT	1
#endif
#ifdef GKT_CONFIG_KEY_LED_MARQUEE_FRAME_TIME_DEFAULT
#define KEY_LED_MARQUEE_FRAME_TIME_DEFAULT	\
	GKT_CONFIG_KEY_LED_MARQUEE_FRAME_TIME_DEFAULT
#else
#define KEY_LED_MARQUEE_FRAME_TIME_DEFAULT	50
#endif
int gkt_key_led_marquee(const uint32_t *frames_key_bits, 
			uint32_t frame_nums, uint32_t flags)
{
	gkt_led_flicker_params_s led_flicker_params;
	int retval = GKT_SUCCESS;

	if (frames_key_bits 
		&& (frame_nums > KEY_LED_MARQUEE_FRAME_MINNUMS) 
		&& (frame_nums <= KEY_LED_MARQUEE_FRAME_MAXNUMS))
	{
		if (g_key_manage.flags & KEY_F_LED_FLICKING) {
			gkt_error("key_led_marquee: busy!\n");
			return GKT_EBUSY;
		}

		retval = key_led_flicker_init(frames_key_bits, frame_nums, flags, 
					&led_flicker_params);
		if (retval != GKT_SUCCESS)
			return retval;

		led_flicker_params.flags |= GKT_LED_FLICKER_F_END_LIGHTEN_NONE;
		if (flags & GKT_KEY_LED_FLICKER_F_REVERSE_BACK)
			led_flicker_params.flags |= GKT_LED_FLICKER_F_REVERSE_BACK;
		if (!led_flicker_params.cycles)
			led_flicker_params.cycles = KEY_LED_MARQUEE_CYCLES_DEFAULT;
		if (!led_flicker_params.frame_time)
			led_flicker_params.frame_time = KEY_LED_MARQUEE_FRAME_TIME_DEFAULT;

		retval = gkt_led_flicker(&led_flicker_params);
		if (GKT_SUCCESS == retval)
			g_key_manage.flags |= KEY_F_LED_FLICKING;
	}
	else if (!frames_key_bits) {
		if (g_key_manage.flags & KEY_F_LED_FLICKING) {
			g_key_manage.flags &= ~KEY_F_LED_FLICKING;
			retval = gkt_led_flicker(NULL);
		}
	}
	else {
		gkt_error("key_led_marquee: invalid params!\n");
		retval = GKT_EPARAM;
	}

	return retval;
}

#ifdef GKT_CONFIG_KEY_LED_FLICKER_CYCLES_DEFAULT
#define KEY_LED_FLICKER_CYCLES_DEFAULT	\
	GKT_CONFIG_KEY_LED_FLICKER_CYCLES_DEFAULT
#else
#define KEY_LED_FLICKER_CYCLES_DEFAULT	3
#endif
#ifdef GKT_CONFIG_KEY_LED_FLICKER_FRAME_TIME_DEFAULT
#define KEY_LED_FLICKER_FRAME_TIME_DEFAULT	\
	GKT_CONFIG_KEY_LED_FLICKER_FRAME_TIME_DEFAULT
#else
#define KEY_LED_FLICKER_FRAME_TIME_DEFAULT	100
#endif
int gkt_key_led_flicker(uint32_t key_bits, uint32_t flags)
{
	gkt_led_flicker_params_s led_flicker_params;
	int retval = GKT_SUCCESS;

	if (key_bits != 0) {
		if (g_key_manage.flags & KEY_F_LED_FLICKING) {
			gkt_error("key_led_flicker: busy!\n");
			return GKT_EBUSY;
		}

		retval = key_led_flicker_init(&key_bits, 1, flags, 
					&led_flicker_params);
		if (retval != GKT_SUCCESS)
			return retval;

		led_flicker_params.flags |= GKT_LED_FLICKER_F_END_RESUME_ORIGIN;
		if (!led_flicker_params.cycles)
			led_flicker_params.cycles = KEY_LED_FLICKER_CYCLES_DEFAULT;
		if (!led_flicker_params.frame_time)
			led_flicker_params.frame_time = KEY_LED_FLICKER_FRAME_TIME_DEFAULT;
		g_key_manage.frames_led_bits[1] = 0;
		led_flicker_params.frame_nums = 2;

		retval = gkt_led_flicker(&led_flicker_params);
		if (GKT_SUCCESS == retval)
			g_key_manage.flags |= KEY_F_LED_FLICKING;
	}
	else {
		if (g_key_manage.flags & KEY_F_LED_FLICKING) {
			g_key_manage.flags &= ~KEY_F_LED_FLICKING;
			retval = gkt_led_flicker(NULL);
		}
	}

	return retval;
}
#endif

void key_led_init(void)
{
	uint32_t i;

	GKT_ASSERT(KEY_LED_MAP_TABLE_SIZE <= GKT_INTBITS);

	g_key_manage.on_key_bits = 0;
	g_key_manage.on_led_bits = 0;
	g_key_manage.all_led_bits = 0;
	for (i = 0; i < KEY_LED_MAP_TABLE_SIZE; i++)
		g_key_manage.all_led_bits |= 1U << sc_key_led_map_table[i];
}
#endif

